import QueryForm from "./query-form";
import ZengModal from "./modal";
import MenuBtns from "./menu-btns";
import { EDIT_MODE, MAX_ROW, EDIT_FLAG } from "./constants";
import { Dropdown, Menu, MenuItem, message, Drawer, Modal, Spin, Popconfirm, Table } from 'ant-design-vue'
import { computed, defineComponent, reactive, ref } from "vue";
import { http } from "/@/utils/request";

const MAX_BUTTON_COUNT = 3

export default defineComponent({
  inheritAttrs: false,
  name: "ZengTable",
  components: { MenuBtns, ZengModal, QueryForm, ADropdown: Dropdown, AMenu: Menu, AMenuItem: MenuItem },
  props: {
    data: Array, // 数组数据，如果有这个数据，组件内将不再主动查询
    rowKey: { // 主键
      type: String,
      default: 'id'
    },
    /**
     * label
     * prop
     * props
     * domType
     * render
     * renderHeader
     */
    columns: { // 表格列
      type: Array,
      required: true
    },
    operations: { // 表格操作按钮
      type: Array,
      // default: () => [...DEFAULT_OPERATIONS]
      default: () => []
    },
    menus: { // 表格上方的功能按钮
      type: Array,
      // default: () => Object.keys(DEFAULT_MENUS_MAP)
      default: () => []
    },
    hideOperation: { // 是否隐藏操作列，隐藏时，operations 值将无效
      type: Boolean,
      default: false
    },
    modalProps: { // a-modal | a-drawer props
      type: Object,
      default: () => ({})
    },
    modalFormProps: { // 弹窗表单的 props
      type: Object,
      default: () => ({})
    },
    modalFormCol: { // 弹窗表单一行几列
      type: Number,
      default: 2
    },
    query: { // 查询表单的对象
      type: Object,
      default: () => ({})
    },
    queryFields: Array, // 查询表单的配置项
    modalFields: Array, // 弹窗表单的配置项
    formatOperation: Function, // 格式化操作按钮，可以在这补全或者删除按钮
    // 查
    queryUrl: String,
    queryAction: Function,
    // 增
    saveUrl: String,
    saveAction: Function,
    // 删
    deleteUrl: String,
    deleteAction: Function,
    deleteContent: { // 删除时提示的内容
      type: String,
      default: '确定要删除吗？'
    },
    editMode: { // inline 行内编辑 | modal 弹窗编辑
      type: String,
      validator: value => Object.values(EDIT_MODE).includes(value)
    }
  },
  setup (props, { attrs }) {
    const tableProps = reactive({
      pagination: {
        total: 0,
        showSizeChanger: true,
        showQuickJumper: true,
        hideOnSinglePage: true,
        size: 'small',
        showTotal: (total, range) => `${range[0]}-${range[1]}共${total}条`,
        layout: 'total, prev, pager, next, sizes, jumper'
      },
      bordered: true,
      rowKey: 'id',
      scroll: { x: true }
    })
    const columns = ref([])
    const tableData = ref([])
    const selections = ref([])
    const editRecord = ref({})
    const editRecordIndex = ref(-1)
    const modal = reactive({
      show: false,
      title: '',
      operation: ''
    })
    const load = reactive({
      table: false,
      download: false,
      import: false,
      delete: {}, // id: boolean
      save: {}
    })

    // 最后一列的 dataIndex 如果是 operation，就会合并两个对象
    const compColumns = computed(() => {
      columns.value = [...props.columns]
      const cs = columns.value
      if (!props.hideOperation) {
        let lastColumn = cs.slice(-1)[0]
        if (lastColumn.dataIndex === 'operation') {
          cs.splice(cs.length - 1, 1)
        } else {
          lastColumn = {}
        }
        cs.push(Object.assign({}, lastColumn, {
          customRender: renderOperation
        }))
      }
      return columns
    })
    const compTableData = computed(() => props.data || tableData.value)
    // antd 是通过 row-selection 完成批量操作的
    const compRowSelection = computed(() => props.menus.toString().includes('batch') ? {} : undefined)
    const compQueryFields = computed(() => props.queryFields.concat({
      render: () => {
        return [
          <a-button type="primary" icon="search" onClick={() => onQuery()}>检索</a-button>,
          // <a-button icon="reload" onClick={() => {
          //   this.$refs.$form.$form.resetFields()
          //   this.onQuery()
          // }}>重置</a-button>
        ]
      }
    }))
    const compModalDomType = computed(() => props.modalFields.length > props.modalFormCol * MAX_ROW ? 'a-drawer' : 'a-modal')

    !(Array.isArray(props.data) && props.data.length) && onQuery()

    function onQuery (page = {}) {
      load.table = true
      const q = Object.assign({ pageIndex: page.current, pageSize: page.pageSize }, props.query)
      if (typeof props.queryAction === 'function') {
        return props.queryAction(q).then(({ data }) => {
          tableData.value = data.list
          this.tableProps.pagination.total = data.totalCount
        }).finally(() => (this.load.table = false))
      }
      if (!props.queryUrl) return
      // 封装的查询方法
      http.get(props.queryUrl, { params: q }).then(({ data }) => {
        tableData.value = data.list
        tableProps.pagination.total = data.totalCount
      }).finally(() => (load.table = false))
    }

    function onDownload () {}

    function onImport () {}

    function onBatchDelete () {
      message.success('批量删除')
    }

    function onCancel () {
      const el = compTableData[editRecordIndex.value]
      el[EDIT_FLAG] = false
      Object.assign(el, editRecord.value)
    }

    function onSave () {
      const rowKeyValue = editRecord.value[props.rowKey]
      load.save[rowKeyValue] = true
      setTimeout(() => {
        message.success('保存' + rowKeyValue)
        load.save[rowKeyValue] = false
        const el = compTableData[editRecordIndex.value]
        el[EDIT_FLAG] = false
      }, 2000)
    }

    /**
     * 显示弹窗，进行表格的查看和修改
     * @param {'update' | 'review'} operation 操作，review 查看 | update 修改
     */
    function onShowModal (operation) {
      if (!props.modalFields?.length) {
        return message.warning('未设置需要修改的字段')
      }
      Object.assign(modal, {
        title: { update: '修改', review: '查看' }[operation],
        operation,
        show: true
      })
    }

    function onDelete (record) {
      const key = props.rowKey
      if (typeof props.deleteAction === 'function') {
        return props.deleteAction(record[key], record, key)
      }
      load.delete[record[key]] = true
      // 默认的删除方法，axios delete deleteUrl record[rowKey]
      setTimeout(() => {
        message.success('删除成功')
        load.delete[record[key]] = false
      }, 2000)
    }

    /**
     * 根据不同的审核状态和配方类型渲染不同的操作按钮。
     * 操作按钮超过 3 个时判断隐藏到 menu 里
     * 注意：
     *  popconfirm 会同时渲染两个出来，解决：
     *   1.表格的操作列是固定的，如 fixed: 'right'，将它改成不固定
     *   2.通过把 popconfirm 隐藏在 menu 里就行了（本质是在表格渲染完之前不要让 popconfirm 出现）
     *   3.不要手动控制 popconfirm 的显示和隐藏
     * @param {string | number} text 操作列文案
     * @param {Object} record 表格行对象，数据对象
     * @param {number} index 索引
     * @return {JSX.Element|*[]}
     */
    function renderOperation (text, record, index) {
      const key = props.rowKey
      if (load.delete[record[key]] || load.save[record[key]]) {
        return <Spin size="small" />
      }
      if (record[EDIT_FLAG]) {
        return [
          <a class="btn--text" onClick={onSave}>保存</a>,
          <a class="btn--text" onClick={onCancel}>取消</a>
        ]
      }
      const domArr = []
      for (const operation of props.operations) {
        domArr.push(getButtonByOperation(operation, { text, record, index }))
      }
      props.formatOperation?.(domArr, record)
      if (domArr.length > MAX_BUTTON_COUNT) {
        const menuArr = domArr.splice(MAX_BUTTON_COUNT, domArr.length - (MAX_BUTTON_COUNT - 1))
        domArr.push(
          <Dropdown>
            <a class="btn--text">更多</a>
            <Menu slot="overlay">
              {menuArr.map((dom, index) => (
                <MenuItem key={index}>{dom}</MenuItem>
              ))}
            </Menu>
          </Dropdown>
        )
      }
      return domArr
    }

    /**
     * 根据操作类型，获取按钮
     * @param {string} operation 操作类型
     * @param {Object} record 表格行数据
     * @param {number} index 表格行索引
     * @return {JSX.Element}
     */
    function getButtonByOperation (operation, { record, index }) {
      switch (operation) {
        case 'delete': {
          // 其实这块只需要控制 popconfirm 是否禁用即可
          return (
            <Popconfirm
              destroy-tooltip-on-hide={true}
              title={props.deleteContent}
              onConfirm={() => onDelete(record)}
            >
              <a class="btn--text btn--danger">删除</a>
            </Popconfirm>
          )
        }
        case 'update': {
          return (
            <a
              class="btn--text"
              onClick={() => {
                editRecord.value = { ...record }
                editRecordIndex.value = index
                if (props.editMode === EDIT_MODE.inline) {
                  return record[EDIT_FLAG] = true
                }
                onShowModal(operation)
              }}
            >修改</a>
          )
        }
        case 'review': {
          return (
            <a
              class="btn--text"
              onClick={() => {
                editRecord.value = record
                onShowModal(operation)
              }}
            >查看</a>
          )
        }
      }
    }

    return () => (
      <section class="zeng-table">
        {
          props.query && Array.isArray(props.queryFields) && props.queryFields.length && (
            <QueryForm
              ref="$form"
              model={props.query}
              layout="inline"
              fields={compQueryFields}
              class="mb-16"
            />
          )
        }
        {
          props.menus && (
            <MenuBtns
              menus={props.menus}
              onSearch={() => onQuery()}
              onDeleteBatch={onBatchDelete}
            />
          )
        }
        <Table
          row-selection={compRowSelection}
          class="mt-16"
          columns={compColumns}
          row-key={props.rowKey}
          data-source={compTableData}
          {...Object.assign({}, tableProps, attrs)}
          onChange={onQuery}
          loading={load.table}
        />
        <ZengModal
          visible={modal.show}
          title={modal.title}
          destroy-on-close
          {...props.modalProps}
          dom-type={compModalDomType}
        >
          <QueryForm
            ref="modalForm"
            model={editRecord}
            fields={props.modalFields}
            col={props.modalFormCol}
            {...props.modalFormProps}
          />
        </ZengModal>
      </section>
    )
  }
})
